package oneD.models;

import oneD.fem.Constraint;
import oneD.fem.Force;
import oneD.fem.Node;
import oneD.fem.method.ArcLengthControl;
import oneD.fem.structure.PrestressTruss;
import oneD.fem.structure.Structure;
import oneD.fem.visualize.TrussVisualizer;
import inf.jlinalg.ArrayVector;
import inf.jlinalg.BLAM;
import inf.jlinalg.IVector;
import inf.jlinalg.SolveFailedException;
import inf.v3d.view.Viewer;

public class NonlinearTwobarKuhl extends ModelViewer {

	@Override
	public PrestressTruss createStructure() {
		PrestressTruss struct = new PrestressTruss();
		double H = 0.7, B1 = 1, B2 = 0.1;
		double E = 2e7, A = 1, rho = 1, alpha = 100, beta = 100;
		double L1 = Math.sqrt(B1 * B1 + H * H);
		// double L2 = Math.sqrt(B2 * B2 + H * H);
		double r = E * A * Math.pow(H, 3) / 3 / Math.sqrt(3) / Math.pow(L1, 3);
		double lambda = -1; // set lambda to 1 if we want to compute instability
							// point
		Constraint c1 = new Constraint(true, false, false);
		Constraint c2 = new Constraint(false, true, false);
		Constraint c3 = new Constraint(false, false, false);
		Force f = new Force(0, lambda * r, 0);
		// create nodes
		Node n1 = struct.addNode(0.0, 0.0, 0.0);
		Node n2 = struct.addNode(B1, H, 0.0);
		Node n3 = struct.addNode(-B2, H, 0.0);
		// apply BCs
		n2.setForce(f);
		n1.setConstraint(c1);
		n2.setConstraint(c2);
		n3.setConstraint(c3);
		// create elements
		struct.addElement(rho, E, A, 0, 0, 1);
		struct.addElement(beta * rho, alpha * E, A, 0, 0, 2);
		// return the new structure
		return struct;
	}

	@Override
	public void initializeVisualizer(Structure struct) {
		this.view_ = new Viewer();
		viz_ = new TrussVisualizer(struct, this.view_);
	}

	@Override
	protected void performLinearModalAnalysis(Structure struct) {
		/*
		 * perform linear modal analysis
		 */
		System.out
				.println("This functionality is not supported for this model");
	}

	@Override
	protected void performNonlinearInstabilityAnalysisUsingDirectComputation(
			Structure struct) {
		/*
		 * instability analysis using direct computation
		 */
		double lambda = 0;
		IVector phi = new ArrayVector(struct.enumerateDOFs());
		BLAM.fill(phi, -1);
		IVector u = struct.createZeroU();
		struct.directLoadControlInstabilityComputation(u, lambda, phi);
	}
	
	@Override
	protected void performLoadDisplacementAnalysisUsingArcLength(
			Structure struct) {
		struct.enumerateDOFs();
		IVector u = struct.createZeroU();
		double lambda = 0.0;
		ArcLengthControl m = new ArcLengthControl(struct);
		// m.setConstraintType("load control");
		// m.setConstraintType("displacement control");
		m.setU0(u);
		m.setLambda0(lambda);
		m.setConstraintType("sphere");
		m.setParameterS(0.01);
		m.setNumStep(100);
		m.setPsi(1.0);
		// m.run();
		// m.print();
		oneD.fem.method.Plot1D p = m.plot();
		p.setVisible(true);
	}

	public static void main(String[] args) throws SolveFailedException {
		NonlinearTwobarKuhl model = new NonlinearTwobarKuhl();
		model.processUserInput();
	}
}
